package edu.odu.cs.sstore.service;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import edu.odu.cs.sstore.domain.Course;
import edu.odu.cs.sstore.domain.User;
import edu.odu.cs.sstore.dto.CourseDTO;
import edu.odu.cs.sstore.dto.DocumentDTO;
import edu.odu.cs.sstore.dto.UserDTO;
import edu.odu.cs.sstore.repository.CourseRepository;
import edu.odu.cs.sstore.repository.DocumentRepository;
import edu.odu.cs.sstore.repository.UserRepository;

@Service(value="courseService")
public class CourseServiceImpl implements CourseService {

	@Autowired
	private CourseRepository courseRepository;
	
	@Autowired
	private UserRepository userRepository;
	
	@Autowired
	private DocumentRepository docRepository;
	
	@Autowired
	private UserContextService userCtx;

	@Transactional(readOnly=true) 
	public CourseDTO getCourse(Long crn) {
		return this.courseRepository.findByCRN(crn).toDTO(true);
	}
	
	@Transactional(readOnly=true)
	public List<CourseDTO> getCourses() {
		User currentUser = userCtx.getCurrentUser();
		List<CourseDTO> dtos = new ArrayList<CourseDTO>();
		if(currentUser!=null) {
			List<Course> courses = this.courseRepository.findByFaculty(currentUser);
			for(Course course : courses)
				dtos.add(course.toDTO(true));
		}
		System.out.println(dtos.size());
		return dtos;
	}

	@Transactional(readOnly=true)
	public List<CourseDTO> getRegisteredCourses() {
		User currentUser = userCtx.getCurrentUser();
		List<CourseDTO> dtos = new ArrayList<CourseDTO>();
		if(currentUser!=null) {
			for(Course course : currentUser.getRegisteredCourses())
				dtos.add(course.toDTO(true));
		}
		System.out.println(dtos.size());
		return dtos;
	}

	@Transactional
	public CourseDTO createCourse(CourseDTO course) {
		
		// Get the respective faculty
		User faculty = userCtx.getCurrentUser();
		
		// Create the course
		Course c = new Course();
		c.setCode(course.getCode());
		c.setCrn(course.getCrn());
		c.setFaculty(faculty);
		c.setName(course.getName());
		this.courseRepository.saveOrUpdate(c);
		
		// Add students
		if(course.getStudents() != null) {
			Iterator<UserDTO> iter = course.getStudents().iterator();
			while(iter.hasNext()) {
				UserDTO student = iter.next();
				c.addStudent(this.userRepository.findById(student.getId()));
			}
		}
		
		// Add documents
		if(course.getDocuments() != null) {
			for(DocumentDTO doc : course.getDocuments()) {
				c.addDocument(this.docRepository.findById(doc.getId()));
			}
		}
		
		// Save again
		this.courseRepository.saveOrUpdate(c);
		
		// Return the DTO of the new course
		return c.toDTO();
		
	}

	@Transactional
	public CourseDTO updateCourse(CourseDTO course) {
		// Create the course
		Course c = this.courseRepository.findByCRN(course.getCrn());
		c.setCode(course.getCode());
		c.setName(course.getName());
		this.courseRepository.saveOrUpdate(c);
		
		// Return the DTO of the new course
		return c.toDTO();
	}

	@Transactional
	public void deleteCourse(Long crn) {
		Course course = this.courseRepository.findByCRN(crn);
		if(course != null)
			this.courseRepository.deleteCourse(course);
	}

}
